/*
 * Copyright (c) 2022 Talkweb Co., Ltd.
 *
 * HDF is dual licensed: you can use it either under the terms of
 * the GPL, or the BSD license, at your option.
 * See the LICENSE file in the root of this repository for complete details.
 */

#include <stdio.h>
#include <stdlib.h>
#include "hdf_log.h"
#include "hdf_sbuf.h"
#include "hdf_io_service_if.h"

#define HDF_LOG_TAG "gpio_test_app_log"
#define LED_ON 123
#define LED_OFF 456

static int32_t OnDevEventReceived(void *priv,  uint32_t id, struct HdfSBuf *reply)
{
    uint16_t pin_val = 0;

    const char *string = HdfSbufReadString(reply);
    if (string == NULL) {
        printf("fail to read string in event reply\n");
        return HDF_FAILURE;
    }

    if(!HdfSbufReadUint16(reply, &pin_val)){
        printf("fail to read uint16 in event reply\n");
        return HDF_FAILURE;
    }

    printf("%s: event reply received: id %u, string %s, pin val %hu\n",  
        (char *)priv, id, string, pin_val);
    return HDF_SUCCESS;
}

static int32_t SendEvent(struct HdfIoService *serv, int32_t id, char *eventData)
{
    int32_t ret = 0;
    struct HdfSBuf *data = NULL;
    struct HdfSBuf *reply = NULL;

    data = HdfSBufObtainDefaultSize();
    if (data == NULL) {
        printf("fail to obtain sbuf data\n");
        ret = HDF_DEV_ERR_NO_MEMORY;
        goto out;
    }

    reply = HdfSBufObtainDefaultSize();
    if (reply == NULL) {
        printf("fail to obtain sbuf reply\n");
        ret = HDF_DEV_ERR_NO_MEMORY;
        goto out;
    }

    if(id == LED_ON){        
        if (!HdfSbufWriteString(data, eventData)) {
            printf("fail to write data\n");
            ret = HDF_FAILURE;
            goto out;
        }
        ret = serv->dispatcher->Dispatch(&serv->object, LED_ON, data, reply);
        if (ret != HDF_SUCCESS) {
            printf("fail to send service call, data");
            goto out;
        }

        uint16_t pin_val = 0;
        const char *string = HdfSbufReadString(reply);
        if (string == NULL) {
            printf("fail to read string in event reply, %d\n", __LINE__);
            ret = HDF_FAILURE;
            goto out;
        }
        if(!HdfSbufReadUint16(reply, &pin_val)){
            printf("fail to read uint16 in event reply, %d\n", __LINE__);
            ret = HDF_FAILURE;
            goto out;
        }
        printf("%s received: string %s, pin val %hu\n",  __func__, string, pin_val);        
    }   

    if(id == LED_OFF){        
        if (!HdfSbufWriteString(data, eventData)) {
            printf("fail to write data\n");
            ret = HDF_FAILURE;
            goto out;
        }
        ret = serv->dispatcher->Dispatch(&serv->object, LED_OFF, data, reply);
        if (ret != HDF_SUCCESS) {
            printf("fail to send service call, reply\n");
            goto out;
        }
    }   

out:
    if(data)
        HdfSBufRecycle(data);
    if(reply)
        HdfSBufRecycle(reply);
    return ret;
}



int32_t main()
{
    char cmdbuf[100];
    
    // 应用程序绑定服务
    struct HdfIoService *serv = HdfIoServiceBind("GPIO_TEST_SERVICE");
    if (serv == NULL) {
        HDF_LOGE("fail to get service %s", "GPIO_TEST_SERVICE");
        return HDF_FAILURE;
    }

    static struct HdfDevEventlistener listener = {
        .callBack = OnDevEventReceived,
        .priv ="Service0"
    };
    // 应用程序注册服务
    if (HdfDeviceRegisterEventListener(serv, &listener) != HDF_SUCCESS) {
        HDF_LOGE("fail to register event listener");
        return HDF_FAILURE;
    }    
    
    do{
        memset(cmdbuf, 0, sizeof(cmdbuf));
        printf("please input cmd(on / off): "); 
        fflush(stdout);               
        scanf("%s", cmdbuf);
        if(!strcmp(cmdbuf, "on")){
            if (SendEvent(serv, LED_ON, cmdbuf) != HDF_SUCCESS) {
                printf("fail to send led on event\n");
                break;
            }
        }else if(!strcmp(cmdbuf, "off")){
            if (SendEvent(serv, LED_OFF, cmdbuf) != HDF_SUCCESS) {
                printf("fail to send led off event\n");
                break;
            }
        }else{
            break;
        }
        
    }while(1);

    if (HdfDeviceUnregisterEventListener(serv, &listener)) {
        HDF_LOGE("fail to unregister listener");
        return HDF_FAILURE;
    }

    HdfIoServiceRecycle(serv);
    return HDF_SUCCESS;
}